﻿using System;
using System.Collections.Generic;
using IrrlichtLime;
using IrrlichtLime.Core;
using Timed;
using IrrlichtLime.Scene;
using IrrlichtLime.Video;
using Iso.Common;

namespace Iso.Core
{
    public class FieldPlayer
    {
        public AnimatedSprite sprite;
        public float speed;
        public float orientation;
        public bool playerControl;
        public PlayerAnimRot rotation;
        public Vector3Df offset;
        public bool colActive = true;

        float tempPosX, tempPosZ;
        string lastAnimName, nextAnimName;

        public FieldPlayer(AnimatedSprite sprite, float speed,
            Vector3Df offset, float orientation = 0)
        {
            this.sprite = sprite;
            this.speed = speed;
            this.orientation = orientation;
            rotation = PlayerAnimRot.S;
            playerControl = false;
            lastAnimName = "";
            nextAnimName = "";
            this.offset = offset;

            // Initial Animation (needed)
            sprite.SetAnimation("NS");
        }

        public void Update()
        {
            sprite.Update();
            if (lastAnimName != nextAnimName && nextAnimName != "" && (sprite.isFinished || lastAnimName.EndsWith("W") || lastAnimName.EndsWith("S")))
            {
                lastAnimName = nextAnimName;
                nextAnimName = "";
                sprite.SetAnimation(lastAnimName);
            }

            if (playerControl)
            {
                if (Keyboard.IsKeyDown(KeyCode.Left) && Keyboard.IsKeyDown(KeyCode.Up)) // LEFT UP
                {
                    rotation = Utility.GetRotation(orientation + 315);

                    tempPosX = 0;
                    tempPosZ = 0;

                    tempPosX += (float)Math.Sin(Utility.ToRadians(orientation - 45)) * Engine.delta * speed;
                    tempPosZ += (float)Math.Cos(Utility.ToRadians(orientation - 45)) * Engine.delta * speed;
                    Vector3Df trasformedPos = sprite.sceneNode.Position + new Vector3Df(tempPosX - offset.X, 0, tempPosZ - offset.Z);

                    if (Collision(trasformedPos))
                    {
                        sprite.sceneNode.Position = new Vector3Df(sprite.sceneNode.Position.X + tempPosX, offset.Y, sprite.sceneNode.Position.Z + tempPosZ);
                        updAnim(true);
                    }
                    else
                        updAnim(false);
                }
                else if (Keyboard.IsKeyDown(KeyCode.Right) && Keyboard.IsKeyDown(KeyCode.Up)) // RIGHT UP
                {
                    rotation = Utility.GetRotation(orientation + 45);

                    tempPosX = 0;
                    tempPosZ = 0;

                    tempPosX += (float)Math.Sin(Utility.ToRadians(orientation + 45)) * Engine.delta * speed;
                    tempPosZ += (float)Math.Cos(Utility.ToRadians(orientation + 45)) * Engine.delta * speed;
                    Vector3Df trasformedPos = sprite.sceneNode.Position + new Vector3Df(tempPosX - offset.X, 0, tempPosZ - offset.Z);

                    if (Collision(trasformedPos))
                    {
                        sprite.sceneNode.Position = new Vector3Df(sprite.sceneNode.Position.X + tempPosX, offset.Y, sprite.sceneNode.Position.Z + tempPosZ);
                        updAnim(true);
                    }
                    else
                        updAnim(false);
                }
                else if (Keyboard.IsKeyDown(KeyCode.Left) && Keyboard.IsKeyDown(KeyCode.Down)) // LEFT DOWN
                {
                    rotation = Utility.GetRotation(orientation + 225);

                    tempPosX = 0;
                    tempPosZ = 0;

                    tempPosX += (float)Math.Sin(Utility.ToRadians(orientation + 225)) * Engine.delta * speed;
                    tempPosZ += (float)Math.Cos(Utility.ToRadians(orientation + 225)) * Engine.delta * speed;
                    Vector3Df trasformedPos = sprite.sceneNode.Position + new Vector3Df(tempPosX - offset.X, 0, tempPosZ - offset.Z);

                    if (Collision(trasformedPos))
                    {
                        sprite.sceneNode.Position = new Vector3Df(sprite.sceneNode.Position.X + tempPosX, offset.Y, sprite.sceneNode.Position.Z + tempPosZ);
                        updAnim(true);
                    }
                    else
                        updAnim(false);
                }
                else if (Keyboard.IsKeyDown(KeyCode.Right) && Keyboard.IsKeyDown(KeyCode.Down)) // RIGHT DOWN
                {
                    rotation = Utility.GetRotation(orientation + 135);

                    tempPosX = 0;
                    tempPosZ = 0;

                    tempPosX += (float)Math.Sin(Utility.ToRadians(orientation + 135)) * Engine.delta * speed;
                    tempPosZ += (float)Math.Cos(Utility.ToRadians(orientation + 135)) * Engine.delta * speed;
                    Vector3Df trasformedPos = sprite.sceneNode.Position + new Vector3Df(tempPosX + offset.X, 0, tempPosZ - offset.Z);

                    if (Collision(trasformedPos))
                    {
                        sprite.sceneNode.Position = new Vector3Df(sprite.sceneNode.Position.X + tempPosX, offset.Y, sprite.sceneNode.Position.Z + tempPosZ);
                        updAnim(true);
                    }
                    else
                        updAnim(false);
                }
                else if (Keyboard.IsKeyDown(KeyCode.Up)) // UP
                {
                    rotation = Utility.GetRotation(orientation);

                    tempPosX = 0;
                    tempPosZ = 0;

                    tempPosX += (float)Math.Sin(Utility.ToRadians(orientation)) * Engine.delta * speed;
                    tempPosZ += (float)Math.Cos(Utility.ToRadians(orientation)) * Engine.delta * speed;
                    Vector3Df trasformedPos = sprite.sceneNode.Position + new Vector3Df(tempPosX, 0, tempPosZ - offset.Z);

                    if (Collision(trasformedPos))
                    {
                        sprite.sceneNode.Position = new Vector3Df(sprite.sceneNode.Position.X + tempPosX, offset.Y, sprite.sceneNode.Position.Z + tempPosZ);
                        updAnim(true);
                    }
                    else
                        updAnim(false);
                }
                else if (Keyboard.IsKeyDown(KeyCode.Left)) // LEFT
                {
                    rotation = Utility.GetRotation(orientation + 270);

                    tempPosX = 0;
                    tempPosZ = 0;

                    tempPosX += (float)Math.Sin(Utility.ToRadians(orientation + 270.0f)) * Engine.delta * speed;
                    tempPosZ += (float)Math.Cos(Utility.ToRadians(orientation + 270.0f)) * Engine.delta * speed;
                    Vector3Df trasformedPos = sprite.sceneNode.Position + new Vector3Df(tempPosX - offset.X, 0, tempPosZ - offset.Z);

                    if (Collision(trasformedPos))
                    {
                        sprite.sceneNode.Position = new Vector3Df(sprite.sceneNode.Position.X + tempPosX, offset.Y, sprite.sceneNode.Position.Z + tempPosZ);
                        updAnim(true);
                    }
                    else
                        updAnim(false);
                }
                else if (Keyboard.IsKeyDown(KeyCode.Right)) // RIGHT
                {
                    rotation = Utility.GetRotation(orientation + 90);

                    tempPosX = 0;
                    tempPosZ = 0;

                    tempPosX += (float)Math.Sin(Utility.ToRadians(orientation + 90.0f)) * Engine.delta * speed;
                    tempPosZ += (float)Math.Cos(Utility.ToRadians(orientation + 90.0f)) * Engine.delta * speed;
                    Vector3Df trasformedPos = sprite.sceneNode.Position + new Vector3Df(tempPosX + offset.X, 0, tempPosZ - offset.Z);

                    if (Collision(trasformedPos))
                    {
                        sprite.sceneNode.Position = new Vector3Df(sprite.sceneNode.Position.X + tempPosX, offset.Y, sprite.sceneNode.Position.Z + tempPosZ);
                        updAnim(true);
                    }
                    else
                        updAnim(false);
                }
                else if (Keyboard.IsKeyDown(KeyCode.Down)) // DOWN
                {
                    rotation = Utility.GetRotation(orientation + 180);

                    tempPosX = 0;
                    tempPosZ = 0;

                    tempPosX += (float)Math.Sin(Utility.ToRadians(orientation + 180.0f)) * Engine.delta * speed;
                    tempPosZ += (float)Math.Cos(Utility.ToRadians(orientation + 180.0f)) * Engine.delta * speed;
                    Vector3Df trasformedPos = sprite.sceneNode.Position + new Vector3Df(tempPosX, 0, tempPosZ - offset.Z);

                    if (Collision(trasformedPos))
                    {
                        sprite.sceneNode.Position = new Vector3Df(sprite.sceneNode.Position.X + tempPosX, offset.Y, sprite.sceneNode.Position.Z + tempPosZ);
                        updAnim(true);
                    }
                    else
                        updAnim(false);
                }
                else
                    updAnim(false);
            }
        }

        private void updAnim(bool walk)
        {
            if (walk)
            {
                if (rotation == PlayerAnimRot.SE)
                    Animate("SEW");
                else if (rotation == PlayerAnimRot.NE)
                    Animate("NEW");
                else if (rotation == PlayerAnimRot.SW)
                    Animate("SWW");
                else if (rotation == PlayerAnimRot.NW)
                    Animate("NWW");
                else if (rotation == PlayerAnimRot.S)
                    Animate("SW");
                else if (rotation == PlayerAnimRot.N)
                    Animate("NW");
                else if (rotation == PlayerAnimRot.W)
                    Animate("WW");
                else if (rotation == PlayerAnimRot.E)
                    Animate("EW"); 
            }
            else
            {
                if (rotation == PlayerAnimRot.SE)
                    Animate("SES");
                else if (rotation == PlayerAnimRot.NE)
                    Animate("NES");
                else if (rotation == PlayerAnimRot.SW)
                    Animate("SWS");
                else if (rotation == PlayerAnimRot.NW)
                    Animate("NWS");
                else if (rotation == PlayerAnimRot.S)
                    Animate("SS");
                else if (rotation == PlayerAnimRot.N)
                    Animate("NS");
                else if (rotation == PlayerAnimRot.W)
                    Animate("WS");
                else if (rotation == PlayerAnimRot.E)
                    Animate("ES");
            }
        }

        public void Animate(string animName)
        {
            nextAnimName = animName;
        }

        public void Remove()
        {
            sprite.Remove();
        }

        public bool Collision(Vector3Df pos)
        {
            return !((Scene)Engine.currentScene).collisionsInverse.ToArray().PointInPolygon(new Vector2Df(pos.X, pos.Z)) &&
                ((Scene)Engine.currentScene).collisions.ToArray().PointInPolygon(new Vector2Df(pos.X, pos.Z))
                || !colActive;
        }
    }
}
